package com.bshinfo.web.base.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

/**
 * Http请求工具类<br/>
 * 
 * 功能描述: 进行Http get post 请求<BR/>
 * 
 * < <BR />
 * 	 1.  <BR/>
 *   2.  <BR/>
 *   3.  <BR/>
 * >
 * 
 * 
 * @author 	[zhangChao]
 * 
 * @see 	[okhttp3.OkHttpClient]
 * 
 * @since 	[JDK 1.7] 
 * 
 * @version [1.0]
 * 
 * @Date    [2017-1-12 11:37:37]
 */
public class HttpUtil 
{
	// 单例对象
	// 定义一个静态私有变量(不初始化，不使用final关键字，使用volatile保证了多线程访问时instance变量的可见性，避免了instance初始化时其他变量属性还没赋值完时，被另外线程调用)
	private static volatile HttpUtil instance = null;
	
	// 请求客户端对象
	private OkHttpClient httpClient;
	
	// 读取超时时间 单位 ms
	private static final long DEFAULT_READ_TIMEOUT = 5000;

	// 连接超时时间 单位 ms
	private static final long DEFAULT_CONNECT_TIMEOUT = 5000;
	
	// 写入超时时间 单位 ms
	private static final long DEFAULT_WRITE_TIMEOUT = 5000;
	
	// 私有构造方法 (对外提供单例)
	private HttpUtil()
	{
		okhttp3.OkHttpClient.Builder ClientBuilder = new okhttp3.OkHttpClient.Builder();  
		// 读取超时  
        ClientBuilder.readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS);
        // 连接超时  
        ClientBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);
        // 写入超时  
        ClientBuilder.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.MILLISECONDS);
        
        httpClient = ClientBuilder.build();  
	}
	
	// 共有的静态方法，返回该类型实例
	public static HttpUtil getInstance()
	{
		// 对象实例化时与否判断（不使用同步代码块，instance不等于null时，直接返回对象，提高运行效率）
        if (instance == null) 
        {
            //同步代码块（对象未初始化时，使用同步代码块，保证多线程访问时对象在第一次创建后，不再重复被创建）
            synchronized (HttpUtil.class) 
            {
                //未初始化，则初始instance变量
                if (instance == null)
                {
                    instance = new HttpUtil();   
                }   
            }   
        }   
        return instance;   
	}
	
	/***
	 * 设置请求头
	 * 
	 * @param  [java.util.Map<String, String>] headersParams
	 * 
	 * @return [okhttp3.Headers] 参数为空则返回null
	 */
	private Headers setHeaders(Map<String,String> headersParams)
	{
		// okhttp3 请求头对象
		Headers headers=null;  
		
	    okhttp3.Headers.Builder headersbuilder=new okhttp3.Headers.Builder();  
	    
	    if(headersParams != null)  
	    {  
	        Iterator<String> iterator = headersParams.keySet().iterator();  
	        
	        String key = "";  
	        
	        while (iterator.hasNext())
	        {  
	            key = iterator.next().toString(); 
	            
	            headersbuilder.add(key, headersParams.get(key));  
	        }  
	    }  
	    
	    headers = headersbuilder.build();  
	      
	    return headers;  
	}
	
	
	/***
	 * POST    请求设置请求体
	 * 
	 * @param  [java.util.Map<String, String>] headersParams
	 * 
	 * @return [okhttp3.RequestBody] 参数为空则返回null
	 */
	private RequestBody SetRequestBody(Map<String, String> BodyParams)
	{  
        RequestBody body = null;  
        
        okhttp3.FormBody.Builder formEncodingBuilder = new okhttp3.FormBody.Builder();  
        
        if(BodyParams != null)
        {  
            Iterator<String> iterator = BodyParams.keySet().iterator();  
            String key = "";  
            while (iterator.hasNext())
            {  
                key = iterator.next().toString();  
                
                formEncodingBuilder.add(key, BodyParams.get(key));  
            }  
        }  
        body=formEncodingBuilder.build();  
        
        return body;  
          
    }  
	
	/***	
	 * GET   	请求方式参数拼接
	 * 
	 * @param 	{String}  		[url]
	 * 
	 * @param 	{java.util.Map} [mapParams]
	 * 
	 * @return 	{String} 		[requestUrl]
	 */
	private String setUrlParams( String url,Map<String, String> mapParams)
	{  
//        String strParams = "";   
//        
//        if(mapParams != null)
//        {  
//            Iterator<String> iterator = mapParams.keySet().iterator();  
//            
//            String key = "";  
//            
//            while (iterator.hasNext()) 
//            {  
//                key = iterator.next().toString();  
//                strParams += "&"+ key + "=" + mapParams.get(key);  
//            }  
//        }     
        
        StringBuffer sb = new StringBuffer();
        
        if (mapParams != null && mapParams.size() > 0)
        {
            Set<Map.Entry<String, String>> entrySet = mapParams.entrySet();
            
            sb.append("?");
            
            for (Map.Entry<String, String> entry : entrySet) 
            {
                sb.append(entry.getKey());
                
                sb.append("=");
                
                try 
                {
                    sb.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
                } 
                catch (UnsupportedEncodingException e)
                {
                    e.printStackTrace();
                }
                
                sb.append("&");
            }
            
            sb.deleteCharAt(sb.length() - 1);
        }
          
        return url + sb.toString();  
    }  
	
	
	
	public JSONObject getJsonExecute
					 (
							 String reqUrl,  Map<String, String> headersParams, Map<String, String> 
							 requestParams,String requestType,Object object
					 ) throws IOException
	{
		
		JSONObject result = new JSONObject();
		
		okhttp3.Request.Builder RequestBuilder = new okhttp3.Request.Builder(); 
		
		// 判断是否是GET请求
		if("GET".equals(requestType))
		{
			RequestBuilder.url(setUrlParams(reqUrl,requestParams));//添加URL地址  
		}
		else if("POST".equals(requestType))
		{
			RequestBuilder.url(reqUrl);
			
			// 设置请求body(参数体)
			RequestBuilder.post(SetRequestBody(requestParams));
		}
		
		// 添加请求头  
		RequestBuilder.headers(setHeaders(headersParams));
		
		// 添加请求标签  
		RequestBuilder.tag(object);
		
		Request request = RequestBuilder.build();  
		
		Call call = httpClient.newCall(request);  
		
		okhttp3.Response response = call.execute();
		
		// 判断当前调用是否成功
		if(response.isSuccessful())
		{
			// 获取返回的字符串
			String strResult = response.body().string();
			
			// 判断是否为空
			if(null==strResult||"".equals(strResult))
			{
				result.put("status", "fail");
				result.put("msg", "返回数据格式错误!");
			}
			else
			{
				// 截取第一个字符
				final char[] strChar = strResult.substring(0, 1).toCharArray();  
		        final char firstChar = strChar[0]; 
		        
		        // 判断开头
		        if(firstChar == '{')
		        {  
		        	result = JSONObject.fromObject(strResult);
		        	result.put("status", "success");
		        }
		        else if(firstChar == '[')
		        {  
		        	JSONArray jsar = JSONArray.fromObject(strResult);
		        	result.put("jsar", jsar);
		        	result.put("status", "success");
		        }
		        else
		        {  
		        	result.put("status", "fail");
					result.put("msg", "返回数据格式错误!");
		        }  
			}
		}
		else
		{
			result.put("status", "fail");
			// 404
			result.put("fali_code", response.code());
			
		}
			
		return result;
	}
	
	
	
	public static void main(String[] args)
	{
		try
		{
//			Map<String,String> paramMap = new HashMap<String,String>();
//			paramMap.put("userId", "2e198c4d96e64bdcb9e9d016c77d196b");
//			JSONObject json = HttpUtil.getInstance().getJsonExecute("http://192.168.1.215:8081/communityEdu/userInfo/getUserInfo.bsh", new HashMap<String,String>(), paramMap, "POST", "test");
//			
//			System.out.println(json.toString());
			
			
			ExecutorService exec = Executors.newFixedThreadPool(30);  
			  
			for (int index = 0; index < 1000; index++) 
			{  
				final int NO = index;  
				
				Runnable run = new Runnable()
				{  
					public void run()
					{  
					  
						try 
						{  
							long time1=System.currentTimeMillis();  
//							URL url = new URL("http://www.baidu.com");  
//							InputStreamReader isr = new InputStreamReader(url.openStream());  
							
							
							Map<String,String> paramMap = new HashMap<String,String>();
							paramMap.put("userId", "2e198c4d96e64bdcb9e9d016c77d196b");
							JSONObject json = HttpUtil.getInstance().getJsonExecute("http://192.168.1.215:8080/communityEdu/userInfo/getUserInfo.bsh", new HashMap<String,String>(), paramMap, "POST", "test");
							
							System.out.println(json.toString());
							
							long time2=System.currentTimeMillis();  
							System.out.print("Thread "+NO+" time:"+(time2-time1)+"ms");  
//							BufferedReader br = new BufferedReader(isr);  
//							String str;  
//							while ((str = br.readLine()) != null)
//							{  
//								System.out.println(str);  
//							}  
//							br.close();  
//							isr.close();  
						  
						} 
						catch (Exception e)
						{  
						  
							e.printStackTrace();  
						  
						}  
					} 
				};
					
				exec.execute(run);  
			}
			
			// 退出线程池  
			exec.shutdown();
			  
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
	}
	
	
}

enum JSON_TYPE
{
	/**JSONObject*/  
    JSON_TYPE_OBJECT,  
    /**JSONArray*/  
    JSON_TYPE_ARRAY,  
    /**不是JSON格式的字符串*/  
    JSON_TYPE_ERROR  
}
